package start.spring.basic.util.common;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 
 * ****************************************************************************
 * 日期操作工具类
 *
 * @author(作者)：xuyongyun	
 * @date(创建日期)：2023年2月17日
 ******************************************************************************
 */
public class DateUtil {

	/**
	 * yyyy-MM-dd
	 */
	public static final String FORMAT_YMD_L = "yyyy-MM-dd";
	
	/**
	 * yyyyMMdd
	 */
	public static final String FORMAT_YMD_S = "yyyyMMdd";
	
	/**
	 * yyyy年MM月dd日
	 */
	public static final String FORMAT_YMD_ZW = "yyyy年MM月dd日";
	
	/**
	 * yyyy-MM
	 */
	public static final String FORMAT_YM_L = "yyyy-MM";

	/**
	 * yyyyMM
	 */
	public static final String FORMAT_YM_S = "yyyyMM";
	
	/**
	 * yyyy年MM月
	 */
	public static final String FORMAT_YM_ZW = "yyyy年MM月";
	
	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public static final String FORMAT_YMDHMS_L = "yyyy-MM-dd HH:mm:ss";

	/**
	 * yyyyMMdd HH:mm:ss
	 */
	public static final String FORMAT_YMDHMS = "yyyyMMdd HH:mm:ss";
	
	/**
	 * yyyyMMddHHmmss
	 */
	public static final String FORMAT_YMDHMS_S = "yyyyMMddHHmmss";
	
	/**
	 * yyyy-MM-dd HH:mm:ss.SSS
	 */
	public static final String FORMAT_YMDHMSSS_L = "yyyy-MM-dd HH:mm:ss.SSS";
	
	/**
	 * yyyyMMddHHmmssSSS
	 */
	public static final String FORMAT_YMDHMSSS_S = "yyyyMMddHHmmssSSS";
	
	/**
	 * 将传入的字符串按传入的格式字符串转换为日期
	 * @param strDate
	 * @param format
	 * @return
	 * @throws ParseException 
	 */
	public static Date parse(String strDate, String format) throws ParseException {
		SimpleDateFormat sdf = null;
		Date date = null;
		sdf = new SimpleDateFormat(format);
		//这个很关键，表明是按严格的校验进行转换，否则，20170404将通过yyyyMM的校验
		sdf.setLenient(false);  	
		// 转换成Date
		date = sdf.parse(strDate);  
		return date;
	}
	

	/**
	 * 日期对象转为字符对象（有格式参数）
	 * 
	 * @param date
	 *            日期
	 * @param format
	 *            日期字符格式
	 * @return String 日期字符串
	 */
	public static String format(Date date, String format) {
		if(date==null) {
			return null;
		}else {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			String dateStr = sdf.format(date);
			return dateStr;
		}
	}
	
	/**
	 * 判断date1是否在date2之前，如果相等，则认为不是在之前，返回false，否则返回true
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static boolean before(Date date1, Date date2) {
		//Date1.after(Date2),当Date1大于Date2时，返回TRUE，当小于等于时，返回false； 这是按秒的比较
		return date1.after(date2);  
	}

	
	 /**
	  * 计算两个日期之间相差的天数
	  * @param date1
	  * @param date2
	  * @return
	  */
	public static double daysBetween(Date date1,Date date2) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date1);
		long time1 = cal.getTimeInMillis();    
		cal.setTime(date2);
		long time2 = cal.getTimeInMillis();  
		double betweenDays=(time2-time1)*1.0/(1000*3600*24);  
		return betweenDays;  
	}
	
	/**
	  * 计算两个日期之间相差的小时
	  * 
	  * @param date1
	  * @param date2
	  * @return
	  */
	public static double hoursBetween(Date date1,Date date2) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date1);
		long time1 = cal.getTimeInMillis();    
		cal.setTime(date2);
		long time2 = cal.getTimeInMillis();  
		double betweenDays=(time2-time1)*1.0/(1000*3600);  
		return betweenDays;  
	}

	/**
	 * 计算传入的日期参数加字符串参数之后的时间
	 * 
	 * @param d
	 * @param day
	 *              单位为天，负数则为向前推
	 * @return
	 */
	public static Date calcTime(Date d, int day) {
		Calendar calendar = new GregorianCalendar();
		calendar.setTime(d);
		calendar.add(Calendar.DATE, day);
		Date nextDate = calendar.getTime();
		return nextDate;
	}
	

	/**
	 * 获得当前日期（有格式参数）
	 * 
	 * @param format
	 *            日期字符格式
	 * @return String 日期
	 * @throws BaseException
	 */
	public static String getCurrentDate(String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		String dateStr = sdf.format(new Date());
		return dateStr;
	}
	
	/**
	 * 获得当前月
	 * @return String 月
	 * @throws BaseException
	 */
	public static String getCurrentMonth() {
		Calendar calendar = Calendar.getInstance();
	
		Date strDateTo = calendar.getTime(); 
		return format(strDateTo,FORMAT_YM_S);
	}

	
	/**
	 * 获得和所传月份相差特定月份的月份
	 *	
	 * @param month 所传月份
	 * @param distinct 相差月份
	 * @return
	 * @throws ParseException
	 * @since           1.0
	 */
	public static String getDistinctMonth(String month,int distinct) throws ParseException {

		SimpleDateFormat sdf= new SimpleDateFormat(FORMAT_YM_S);
		Date date =sdf.parse(month);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, distinct);
		return format(calendar.getTime(),FORMAT_YM_S);
	}
	
	/**
	 * 判断日期相隔几个月
	 * @param start
	 * @param end
	 * @return
	 */
	public static int getMonth(Date start, Date end) {
        if (start.after(end)) {
            Date t = start;
            start = end;
            end = t;
        }
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(start);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(end);
        Calendar temp = Calendar.getInstance();
        temp.setTime(end);
        temp.add(Calendar.DATE, 1);

        int year = endCalendar.get(Calendar.YEAR)
                - startCalendar.get(Calendar.YEAR);
        int month = endCalendar.get(Calendar.MONTH)
                - startCalendar.get(Calendar.MONTH);

        if ((startCalendar.get(Calendar.DATE) == 1)
                && (temp.get(Calendar.DATE) == 1)) {
            return year * 12 + month + 1;
        } else if ((startCalendar.get(Calendar.DATE) != 1)
                && (temp.get(Calendar.DATE) == 1)) {
            return year * 12 + month;
        } else if ((startCalendar.get(Calendar.DATE) == 1)
                && (temp.get(Calendar.DATE) != 1)) {
            return year * 12 + month;
        } else {
            return (year * 12 + month - 1) < 0 ? 0 : (year * 12 + month);
        }
    }
	
	/**
	 * 
	 * 校验日期是否合法
	 * @param format
	 * @param datestr
	 * @return
	 * @since           1.0
	 */
	public static boolean isValidDate(String format,String datestr) {
		boolean convertSuccess = true;
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		try {
			sdf.setLenient(false);
			sdf.parse(datestr);
		} catch (ParseException e) {
			convertSuccess = false;
		}
		return convertSuccess;
	}
	
	/**
	 * 日期字符串转毫秒
	 * @param str 日期
	 * @param type 格式
	 * @return
	 * @throws ParseException 
	 */
	public static long stringDateToMillis(String str,String type) throws ParseException{
		Calendar c = Calendar.getInstance();
		long currentTime = 0L;
		c.setTime(new SimpleDateFormat(type).parse(str));
		currentTime = c.getTimeInMillis();
		return  currentTime;
		
	}
	
	/**
	 * 日期字符串转毫秒
	 * @param str 日期
	 * @param type 格式
	 * @return
	 * @throws ParseException 
	 */
	public static long localDateTimeToMillis(LocalDateTime localDateTime) {
		return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
	}

	/**
	 * 获取指定年月的第一天
	 * @param year
	 * @param month
	 * @return
	 */
	public static String getFirstDayOfMonth1(int year, int month) {
		Calendar cal = Calendar.getInstance();
		//设置年份
		cal.set(Calendar.YEAR, year);
		//设置月份
		cal.set(Calendar.MONTH, month-1);
		//获取某月最小天数
		int firstDay = cal.getMinimum(Calendar.DATE);
		//设置日历中月份的最小天数
		cal.set(Calendar.DAY_OF_MONTH,firstDay);
		//格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		return sdf.format(cal.getTime());
	}

	/**
	 * 获取指定年月的最后一天
	 * @param year
	 * @param month
	 * @return
	 */
	public static String getLastDayOfMonth1(int year, int month) {
		Calendar cal = Calendar.getInstance();
		//设置年份
		cal.set(Calendar.YEAR, year);
		//设置月份
		cal.set(Calendar.MONTH, month-1);
		//获取某月最大天数
		int lastDay = cal.getActualMaximum(Calendar.DATE);
		//设置日历中月份的最大天数
		cal.set(Calendar.DAY_OF_MONTH, lastDay);
		//格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		return sdf.format(cal.getTime());
	}
}
